package org.lboot.flow.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.lboot.core.domain.PageResultDTO;
import org.lboot.core.domain.ResponseDTO;
import org.lboot.flow.module.audit.FlowAudit;
import org.lboot.flow.module.audit.FlowAuditService;
import org.lboot.flow.module.audit.params.FlowAuditQueryParams;
import org.lboot.flow.module.work.FlowWork;
import org.lboot.flow.module.work.FlowWorkService;
import org.lboot.jpa.utils.JpaDataUtil;
import org.lboot.starter.plugin.rsr.RsrTree;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("flow")
@Api(tags = "流程审计管理")
@AllArgsConstructor
@RsrTree("流程引擎")
public class FlowAuditController {
    FlowAuditService auditService;

    FlowWorkService flowWorkService;

    @GetMapping("audits")
    @ApiOperation(value = "审计信息列表")
    public ResponseDTO<Object> auditQueryList(FlowAuditQueryParams params){
        Pageable pageable = JpaDataUtil.buildPageable(params);
        // 构建谓词查询
        Specification<FlowAudit> spec = (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            // 流程实例ID
            if (Validator.isNotEmpty(params.getFlowWorkId())){
                Predicate p = cb.equal(root.get("flowWorkId").as(String.class),params.getFlowWorkId());
                list.add(p);
            }
            // 流程节点ID
            if (Validator.isNotEmpty(params.getFlowNodeId())){
                Predicate p = cb.equal(root.get("flowNodeId").as(String.class),params.getFlowNodeId());
                list.add(p);
            }
            // 流程节点名称
            if (Validator.isNotEmpty(params.getFlowNodeName())){
                Predicate p = cb.equal(root.get("flowNodeName").as(String.class),params.getFlowNodeName());
                list.add(p);
            }
            // 节点类型ID
            if (Validator.isNotEmpty(params.getFlowNodeType())){
                Predicate p = cb.equal(root.get("flowNodeType").as(String.class),params.getFlowNodeType());
                list.add(p);
            }
            // 审计结果
            if (Validator.isNotEmpty(params.getAuditResult())){
                Predicate p = cb.equal(root.get("auditResult").as(String.class),params.getAuditResult());
                list.add(p);
            }
            // 流程审计意见
            if (Validator.isNotEmpty(params.getRemark())){
                Predicate p = cb.equal(root.get("remark").as(String.class),params.getRemark());
                list.add(p);
            }
            // 流程审计人
            if (Validator.isNotEmpty(params.getCreateUserId())){
                Predicate p = cb.equal(root.get("createUserId").as(String.class),params.getCreateUserId());
                list.add(p);
            }
            Predicate[] predicates = new Predicate[list.size()];
            return cb.and(list.toArray(predicates));
        };
        return ResponseDTO.succData(
                auditService.getAll(pageable,spec)
        );
    }

    FlowWork mathFlow(List<FlowWork> works, String id){
        for (FlowWork work:works){
            if (work.getId().equals(id)){
                return work;
            }
        }
        return null;
    }

    // 获取审计信息关联的流程实例信息
    @GetMapping("audits/works")
    @ApiOperation(value = "审计流程列表")
    public ResponseDTO<Object> auditWorkQueryList(FlowAuditQueryParams params){
        Pageable pageable = JpaDataUtil.buildPageable(params);
        // 构建谓词查询
        Specification<FlowAudit> spec = (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            // 流程实例ID
            if (Validator.isNotEmpty(params.getFlowWorkId())){
                Predicate p = cb.equal(root.get("flowWorkId").as(String.class),params.getFlowWorkId());
                list.add(p);
            }
            // 流程节点ID
            if (Validator.isNotEmpty(params.getFlowNodeId())){
                Predicate p = cb.equal(root.get("flowNodeId").as(String.class),params.getFlowNodeId());
                list.add(p);
            }
            // 节点类型ID
            if (Validator.isNotEmpty(params.getFlowNodeType())){
                Predicate p = cb.equal(root.get("flowNodeType").as(String.class),params.getFlowNodeType());
                list.add(p);
            }
            // 审计结果
            if (Validator.isNotEmpty(params.getAuditResult())){
                Predicate p = cb.equal(root.get("auditResult").as(String.class),params.getAuditResult());
                list.add(p);
            }
            // 流程审计意见
            if (Validator.isNotEmpty(params.getRemark())){
                Predicate p = cb.equal(root.get("remark").as(String.class),params.getRemark());
                list.add(p);
            }
            // 流程审计人
            if (Validator.isNotEmpty(params.getCreateUserId())){
                Predicate p = cb.equal(root.get("createUserId").as(String.class),params.getCreateUserId());
                list.add(p);
            }
            Predicate[] predicates = new Predicate[list.size()];
            return cb.and(list.toArray(predicates));
        };
        PageResultDTO<FlowAudit> pageResultDTO = auditService.getAll(pageable,spec);
        List<FlowAudit> audits = pageResultDTO.getContent();
        List<String> flowWorkIds = audits.stream().map(FlowAudit::getFlowWorkId).collect(Collectors.toList());
        // 提取流程实例列表
        List<FlowWork> works = flowWorkService.batchGet(flowWorkIds);
        PageResultDTO<Map<String, Object>> workPageResultDTO = new PageResultDTO<>();
        List<Map<String,Object>> result = new ArrayList<>();
        for (FlowAudit audit:audits){
            String flowWorkId = audit.getFlowWorkId();
            FlowWork flow = mathFlow(works, flowWorkId);
            if (Validator.isNotEmpty(flow)){
                // 转化为Map
                Map<String, Object> flowMap = BeanUtil.beanToMap(flow);
                // 设置审计信息
                flowMap.put("auditNodeId", audit.getFlowNodeId());
                flowMap.put("auditNodeName", audit.getFlowNodeName());
                flowMap.put("auditNodeType", audit.getFlowNodeType());
                flowMap.put("auditResult", audit.getAuditResult());
                flowMap.put("auditRemark", audit.getRemark());
                result.add(flowMap);
            }

        }
        BeanUtil.copyProperties(pageResultDTO, workPageResultDTO, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        workPageResultDTO.setContent(result);
        return ResponseDTO.succData(workPageResultDTO);
    }
}
